"""
@author: xxw
@file: 03-01.线程锁-互斥锁.py
@time: 2023/6/26 20:12
"""
# 线程在同一个进程内是共享资源的
# 很容易发生资源争抢，产生脏数据

#允许某一部分资源，同时只有一个线程访问    互斥锁:解决资源争抢（Lock 、RLock）
# import threading
# import time
#
# num = 0
# def add_num(i):
#     # 使用with语句管理的对象 -- 上下文管理器对象
#     # 上下文管理器对象 __enter__   __exit__
#     # __enter__方法做一些初始化工作
#     # __exit__方法做一些结束收尾工作   释放资源
#     with lock:
#         global num
#         time.sleep(1)
#         num += i
#         print(f"num is {num}")
#
#
# t_list = []
#
# # 生成一个锁实例
# lock = threading.Lock()
# print(dir(lock))
# for i in range(10):
#     t = threading.Thread(target=add_num, args=(i,))
#     t.start()
# [t.join() for t in t_list]
#
# print("end....")
#
# # Lock  原始锁  获取锁之前不做判断，直到获取到锁为止
# # RLock 重入锁     获取锁之前先判断，如果自己有了锁，就立即返回
#
# import threading
# lock1 = threading.Lock()
# lock2 = threading.RLock()
#
# lock2.acquire()
# print("lock1 acqurie 1")
# lock2.acquire()
# print("lock1 acqurie 2")
# lock2.release()
# print("lock1 release 1")
# lock2.release()
# print("lock1 release 2")

# 产生死锁

from threading import Thread, Lock
from time import sleep

class Account:
    def __init__(self, id, balance, lock):
        self.id = id
        self.balance = balance
        self.lock = lock

    # 取钱
    def withdraw(self, amount):
        self.balance -= amount

    # 存钱
    def deposit(self, amount):
        self.balance += amount

    # 查看余额
    def get_balance(self):
        return self.balance

# 生成两个账户
xxw = Account("肖祥武", 10000, Lock())
chenli = Account("陈理", 5000, Lock())

# 转账函数   谁的账户金额要动，就需要先上锁
#from_ 为转出账户，to为转入账户，amount 为金额
def transfer(from_,to_,amount):
    if from_.lock.acquire():
        from_.withdraw(amount) #from 账户取钱
        sleep(1)
        print("wait....")
        if to_.lock.acquire():
            to_.deposit(amount)
            to_.lock.release()
        from_.lock.release()
    print(f"{from_.id} 向{to_.id} 转了{amount}元 ")

t1 = Thread(target=transfer, args=(chenli,xxw,100))
t2 = Thread(target=transfer, args=(xxw,chenli,1000))
t1.start()
t2.start()
t1.join()
t2.join()

print(chenli.balance)
print(xxw.balance)

# 避免产生死锁
# 尽量避免同一个线程对多个lock进行锁定
# 多个线程对多个lock进行锁定，尽量保证他们以相同的顺序加锁
# 设置超时时间